try:
    #from earthdawn.edactions import flag
    from earthdawn.edlogin import doCreateCharacterRace, doCreateCharacterSex, doCreateCharacterPassion, doCreateCharacterDiscipline
    from earthdawn.edlogin import doCreateCharacterStats, doCreateCharacterAttributeDependendentTraits, doCreateCharacterDescription
    earthdawn = True
except:
    earthdawn = False

import sha, re
import tables
from random import randrange, getrandbits
from asynchat import simple_producer
cu = tables.cu

from model import Select, Insert
Insert = Insert()
Select = Select()

from TelnetIAC import TelnetTalk

import template as tpl

try:
    motd = ""
    mot = open("motd.txt", "r")
    bou = mot.read()
    mot.close()
    bou = bou.splitlines()
    for i in bou:
        motd += i + '\r\n'

except:
    print "File \'motd.txt\' not found, login prompt set to default."
    motd = "MOTD not set.\r\n\r\nLogin:"

class MiniProducer:
    def __init__(self, contents):
        self.contents = contents

    def more(self):
        c = self.contents
        self.contents = None
        return c

class EndSession(Exception): pass

class FirstLogin:
    """Class to manage state while logging in user"""

    def __init__(self, server, addr):
        self.server = server
        self.ipaddr = addr
        self.line = None
        self.plname = None
        self.email = None
        self.ansi = None
        self.step = 1
        self.check = 0
        self.nak = []
        self.enc_pass = ''

    def echo_off(self, session):
        #session.push("\033[8m\xff\373\001") # ECHO OFF
        session.push("\xff\373\001") # ECHO OFF

    def echo_on(self, session):
        #session.push("\033[8m\xff\374\001") # ECHO ON
        session.push("\xff\374\001") # ECHO ON

    def generate_salt(self):
        salt = ""
        possible = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.;,=+!:?$%@-_"

        while len(salt) < 64:
            char = possible[randrange(len(possible))]
            if salt.find(char) == -1:
                salt += char

        return salt

    def encpass(self, ppass, salt):
        ma = sha.new()
        ma.update(salt)
        ma.update(ppass)
        return ma.hexdigest()

    def check_password(self, passtest):
        self.cchk = Select.getPassword(self.plname)

        self.test = self.encpass(passtest, self.cchk[1])
        if self.test == self.cchk[0]: return 0
        else: return -1
        
    def check_ban(self, uname):
        self.bchk = Select.getBan(uname)

        if self.bchk[0] == 1: return 1
        else: return 0

    def handle(self, session, cmd):
        """ This is ugly. asynchat doesn't implement interactive sessions so we have
            to simulate a dialog using a counter that is incremented at every step."""

        if not cmd: cmd = " "

        # Filter the telnet commands
        self.tiac = TelnetTalk()
        self.ndata = self.tiac.listen(cmd)
        self.cmd = self.ndata[0]

        session.push(self.ndata[1]) # Reply accordingly

        if self.step == 1:
            self.plname = self.cmd.lower().strip()
            if not self.plname:
                session.push(tpl.NAME_NO + tpl.NAME_INPUT)
                return
            if not self.plname.isalpha():
                session.push(tpl.NAME_ALPHA + tpl.NAME_INPUT)
                return

            wrongname = False
            badnames = open('badnames', 'r')
            for naughtyword in badnames:
                if naughtyword.strip() in self.plname:
                    wrongname = True
                    break
            badnames.close()

            if wrongname:
                session.push(tpl.NAME_BAD + tpl.NAME_INPUT)
                return

            try:
                self.nak = Select.getPlayerByName(self.plname)
                session.push(str(tpl.WELCOME % self.nak[1].capitalize()))
                session.push(tpl.PASSWORD)
                self.echo_off(session)
                self.step = 5 # Existing user
            except: 
                session.push(tpl.WELCOME_NEW)
                self.plname = str(self.plname)
                session.push(tpl.NAME_IS % self.plname.capitalize())
                session.push(tpl.PASSWORD)
                self.echo_off(session)
                self.step = 2 # New user

        elif self.step == 2:
            #self.echo_on(session)
            self.fpass = self.cmd
            if not self.fpass:
                session.push(tpl.PASSWORD)
                self.echo_off(session)
                return
            else:
                session.push(tpl.PASSWORD_CONFIRM)
                self.echo_off(session)
                self.step = 3

        elif self.step == 3:
            self.spass = self.cmd
            if self.fpass == self.spass:
                self.echo_on(session)
                session.push(tpl.ANSI)
                self.step = 6
            else:
                session.push(tpl.PASSWORD_MISMATCH)
                session.push(tpl.PASSWORD)
                self.echo_off(session)
                self.step = 2

        elif self.step == 5:
            self.echo_on(session)

            if not self.cmd:
                session.push(tpl.PASSWORD)
                self.echo_off(session)
                return

            if self.check_password(self.cmd) == 0:
                # Check if the user is banned.
                if self.check_ban(self.plname) == 1:
                    session.push(tpl.BANNED)
                    session.close()
                else:
                    session.push(tpl.LOGIN + tpl.PRESS_ENTER)
                    self.step = 8
            else:
                session.push(tpl.PASSWORD_WRONG)
                session.push(tpl.PASSWORD)
                self.echo_off(session)

        elif self.step == 6:
            self.echo_on(session)
            self.colors = cmd.lower()
            if (self.colors == "y") or (self.colors == "yes"):
                self.ansi = 'on'
            else:
                self.ansi = 'off'
            session.push(tpl.EMAIL)
            self.step = 7

        elif self.step == 7: # CHANGE        
            if (earthdawn):
                emailreg = re.compile('^[0-9a-z_.+\-]+@[0-9a-z_.\-]+\.[a-z]{2,4}', re.IGNORECASE)
                if emailreg.match(self.cmd) != None:
                    self.email = self.cmd
                    session.push('Please enter the RACE for your character\nYour choices are dwarf, elf, human, obsidiman, ork, troll, t\'skrang or windling\n')
                    self.step = 71
                else:
                    session.push(tpl.EMAIL_BAD)
                    session.push(tpl.EMAIL)
                    self.step = 7
            else:
                #self.echo_on(session)
                emailreg = re.compile('^[0-9a-z_.+\-]+@[0-9a-z_.\-]+\.[a-z]{2,4}', re.IGNORECASE)
                if emailreg.match(self.cmd) != None:
                    self.email = self.cmd
                    self.step = 8
                    self.createUser(session, self.plname, self.fpass)
                else:
                    session.push(tpl.EMAIL_BAD)
                    session.push(tpl.EMAIL)
                    self.step = 7

        elif self.step == 8:
            self.nak = Select.getIP(self.plname)

            if self.nak[1] != None and self.nak[1] != "127.0.0.1":
                session.push(tpl.LOGIN_ALREADY_IN)
                session.close()
            else:
                # Store some basic info into the socket object.
                session.p_id = self.nak[0]
                session.pname = str(self.plname.capitalize())
                
                #store almost evertything in socket - will measure memory footprint later and perhaps revert to DB access instead
                playerData = Select.getAllPlayerData(session.p_id)
                session.description = playerData[0]
                session.discipline = playerData[1]
                session.circle = playerData[2]
                session.race = playerData[3]
                session.gender = playerData[4]
                session.age = playerData[5]
                session.spouse_name = playerData[6]
                session.dexterity = playerData[7]
                session.strength = playerData[8]
                session.toughness = playerData[9]
                session.perception = playerData[10]
                session.willpower = playerData[11]
                session.charisma = playerData[12]
                session.initiative = playerData[13]
                session.fly = playerData[14]
                session.max_carry = playerData[15]
                session.max_lift = playerData[16]
                session.physical_defense = playerData[17]
                session.spell_defense = playerData[18]
                session.social_defense = playerData[19]
                session.normal_armor = playerData[20]
                session.mystical_armor = playerData[21]
                session.wound_threshold = playerData[22]
                session.damage = playerData[23]
                session.wound = playerData[24]
                session.unconscious_rating = playerData[25]
                session.death_rating = playerData[26]
                session.blood_magic_cost = playerData[27]
                session.recovery_tests_left = playerData[28]
                session.recovery_tests_total = playerData[29]
                session.karma_dice = playerData[30]
                session.karma_current = playerData[31]
                session.karma_max = playerData[32]
                session.legend_unspent = playerData[33]
                session.legend_total = playerData[34]
                session.passion = playerData[35]

                session.push("> ")
                session.enter(self.server.enterg)
        
        elif self.step == 71:
            if (doCreateCharacterRace(self, session)) == True:
                session.push('Please enter the gender of your character (m/f)\n')

                self.step = 72
        elif self.step == 72:
            if (doCreateCharacterSex(self, session)) == True:
                session.push('Please enter the Passion your character worships.  Your choices are\nChorrolis \
			       \nDis\nFloranuus\nGarlen\nJaspree\nLochost\nMynbruje\nRaggok\nThystonius \
			       \nUpandal\nVestrial\nnone\n(you can change this later if your unsure)\n')
                self.step = 73
        elif self.step == 73:
            if (doCreateCharacterPassion(self, session)) == True:
                session.push('Please enter your character\'s discipline.  Your choices are \
                \nair sailor\narcher\nbeastmaster\ncavalryman\nelementalist \
                \nillusionist\nnethermancer\nscout\nsky raider\nswordmaster \
                \nthief\ntroubadour\nwarrior\nweaponsmith\nwizard\n')
                self.step = 74
        elif self.step == 74:
            if (doCreateCharacterDiscipline(self, session)) == True:
                #session.push('Please enter a description for your character')
                self.step = 75
        elif self.step == 75:
            if (doCreateCharacterStats(self, session)) == True:
                session.push('Please enter a description for your character.\n')
                self.step = 76
        elif self.step == 76:
            if (doCreateCharacterDescription(self, session)) == True:
                self.step = 77
        elif self.step == 77:
            self.createUser(session, self.plname, self.fpass)
            self.step = 8
            
            
            
#self.step = 7

            
            
            
            #while (doCreateCharacterRace(self, session)) == False:
                #pass
            #while (doCreateCharacterSex(self, session)) == False:
                #pass
            #while (doCreateCharacterPassion(self, session)) == False:
                #pass
            #while (doCreateCharacterDiscipline(self, session)) == False:
                #pass
            #while (doCreateCharacterStats(self, session)) == False:
                #pass
            #while (doCreateCharacterAttributeDependendentTraits(self, session)) == False:
                #pass
            #while (doCreateCharacterDescription(self, session)) == False:
                #pass
            #self.createUser(session, self.plname, self.fpass)
            #self.step = 8

        else:
            session.push(tpl.ERROR_CRITICAL)
            
            
    #if (earthdawn):
        #from earthdawn.edlogin import createUser
    #else:
    def createUser(self, session, pname, ppass):
        self.salty = self.generate_salt()
        self.truepass = self.encpass(ppass, self.salty)

        #self.test = (pname, self.email, self.truepass, self.salty, self.ansi)
        self.test = (pname, self.email, self.truepass, self.salty, 0, self.description, self.ansi, self.discipline, self.circle, \
         self.race, self.gender, self.age, self.spouse_name, self.dexterity, self.strength, self.toughness, self.perception, \
         self.willpower, self.charisma, self.initiative, self.fly, self.max_carry, self.max_lift, self.physical_defense, \
         self.spell_defense, self.social_defense, self.normal_armor, self.mystical_armor, self.wound_threshold, self.damage, \
         self.wound, self.unconscious_rating, self.death_rating, self.blood_magic_cost, self.recovery_tests_left, \
         self.recovery_tests_total, self.karma_dice, self.karma_current, self.karma_max, self.legend_unspent, self.legend_total, \
         self.passion)
        
        ##store almost evertything in socket - will measure memory footprint later and perhaps revert to DB access instead
        #session.description = self.description
        #session.discipline = self.discipline
        #session.circle = self.circle
        #session.race = self.race
        #session.gender = self.gender
        #session.age = self.age
        #session.dexterity = self.dexterity
        #session.strength = self.strength
        #session.toughness = self.toughness
        #session.perception = self.perception
        #session.willpower = self.willpower
        #session.charisma = self.charisma
        #session.initiative = self.initiative
        #session.fly = self.fly
        #session.max_carry = self.max_carry
        #session.max_lift = self.max_lift
        #session.physical_defense = self.physical_defense
        #session.spell_defense = self.spell_defense
        #session.social_defense = self.social_defense
        #session.normal_armor = self.normal_armor
        #session.mystical_armor = self.mystical_armor
        #session.wound_threshold = self.wound_threshold
        #session.damage = self.damage
        #session.wound = self.wound
        #session.unconscious_rating = self.unconscious_rating
        #session.death_rating = self.death_rating
        #session.blood_magic_cost = self.blood_magic_cost
        #session.recovery_tests_left = self.recovery_tests_left
        #session.recovery_tests_total = self.recovery_tests_total
        #session.karma_dice = self.karma_dice
        #session.karma_current = self.karma_current
        #session.karma_max = self.karma_max
        #session.legend_unspent = self.legend_unspent
        #session.legend_total = self.legend_total
        #session.passion = self.passion
        

        #Insert.newPlayer(self.test)
        Insert.ednewPlayer(self.test)

        session.push(tpl.NEW_PLAYER + tpl.PRESS_ENTER)

    def add(self, session):
        # First session reference
        self.session = session
        session.push(motd)
        

